#pragma once

#include <xpam/misc/nocopy.h>
#include <xpam/bind.h>
#include <xpam/event_handler.h>
#include <xpam/size.h>
#include <xpam/point.h>
#include <xpam/rectangle.h>
#include <xpam/structure.h>
#include <xpam/exception.h>

#include <string>
#include <map>
#include <vector>

namespace xpam
{
	namespace ui
	{
        class dc;

		class window
		{
            friend class window_utils;
        public:
            window();
            window(void * h) : _internal_handle(h) { };
            window(int h) : _internal_handle((void*)h) { };
            ~window();
		public:
            void create(const std::string & cls, int class_style, const std::string & title, int window_style, int window_style_ex, int x, int y, int width, int height, const window & parent);
            void create(const std::wstring & cls, int class_style, const std::wstring & title, int window_style, int window_style_ex, int x, int y, int width, int height, const window & parent);
            void destroy();
		public:
            template<typename _Char, typename _Int>
            void create(const std::basic_string<_Char> & cls, const std::basic_string<_Char> & title, int ws, int wsex, const xpam::rectangle<_Int> & rt, const window & parent = window())
            {
                create(cls, 0, title, ws, wsex, rt.x(), rt.y(), rt.width(), rt.height(), parent);
            }

            template<typename _Char, typename _Int>
            void create(const std::basic_string<_Char> & cls, const std::basic_string<_Char> & title, int ws, int wsex, const xpam::size<_Int> & sz, const window & parent = window())
            {
                create(cls, 0, title, ws, wsex, 0x80000000, 0x80000000, sz.width, sz.height, parent);
            }

            template<typename _Char, typename _Int>
            void create(const std::basic_string<_Char> & cls, const std::basic_string<_Char> & title, int ws, int wsex, const xpam::point<_Int> & pt, const xpam::size<_Int> & sz, const window & parent = window())
            {
                create(cls, 0, title, ws, wsex, pt.x, pt.y, sz.width, sz.height, parent);
            }

		public:
            void show();
            void hide();
            bool is_show();
		public:
            int get_id();
            void set_id(int id);
		public:
            std::string get_text();
            void set_text(const std::string & text);
        private:
            void * _internal_handle;
		public:
            bool is_valid_handle();
            void * get_internal_handle() const { return _internal_handle; }
        public:
            static void quit();
            void invalidate();
            void update_layered(dc & dc);
		public:
            xpam::rectangle<int> rectangle();
            void position(const xpam::point<int> & pt);
		};
    }
}